import {
    computed, getCurrentInstance, reactive, Ref, toRefs, watch, watchEffect,
} from 'vue';
import { Tracker } from '@/types/tracker';
import { Company } from '@/types/company';
import { ExportType } from '@/types/export';
import { ElMessage } from 'element-plus';
import { CompanyPriceValue, getPriceAndValue } from './price';

const exportMarkdownHeader = '| 仓位占比 | 公司名称 | 当前市值 | 年内买点 | 年内卖点 | 三年后估值 | 年内涨幅 |\n'
+ '|:---:|:---:|:---:|:---:|:---:|:---:|:---:|\n';

function saveTracker(tracker: Tracker) {
    localStorage.setItem(KEY, JSON.stringify(tracker));
}

function readTracker() {
    const tracker = JSON.parse(localStorage.getItem(KEY) || DEFAULT_TRACKER_VALUE) as Tracker;
    tracker.date = new Date();
    if (!tracker.companies) {
        tracker.companies = [];
    }
    const companyList: Company[] = [];
    tracker.companies.forEach((company) => companyList.push(new Company(company)));
    tracker.companies = companyList;
    return tracker;
}

const KEY = 'tracker_key';
const DEFAULT_TRACKER_VALUE = '{"cash":0,"exchangeRate":0,"companies":[]}';

export function useTracker() {
    const state = reactive<Tracker>(readTracker());

    watch(
        () => state,
        () => {
            saveTracker(state);
        },
        { deep: true },
    );

    watch(
        () => [state.cash, ...state.companies],
        async () => {
            await updateCompanyValuePercentage();
        },
    );

    function shouldUseExchangeRate(company: Company) {
        return company.code && company.code.startsWith('hk');
    }

    async function updateCompanyPriceValue() {
        const prices: CompanyPriceValue[] = await getPriceAndValue(state.companies.map((c) => c.code));
        const exchangeRate = parseFloat(state.exchangeRate);
        state.companies.forEach((company: Company) => {
            const priceValue = prices.find((p) => p.code === company.code);
            if (priceValue) {
                company.price = !Number.isNaN(priceValue.price) ? priceValue.price : undefined;
                company.marketValue = !Number.isNaN(priceValue.value)
                    ? (priceValue.value * (shouldUseExchangeRate(company) ? exchangeRate : 1)) : undefined;
            }
        });
    }

    async function updateCompanyValuePercentage() {
        await updateCompanyPriceValue();

        const exchangeRate = parseFloat(state.exchangeRate);
        const totalValue = state.companies.reduce((total, current) => {
            if (current.shares && current.price) {
                if (shouldUseExchangeRate(current)) {
                    return total + current.shares * current.price * exchangeRate;
                }
                return total + current.shares * current.price;
            }
            return total;
        }, parseFloat(state.cash) ?? 0);

        state.companies.forEach((company: Company) => {
            if (company.shares && company.price) {
                if (shouldUseExchangeRate(company)) {
                    company.percentage = ((company.shares * company.price * exchangeRate) / totalValue) * 100;
                } else {
                    company.percentage = ((company.shares * company.price) / totalValue) * 100;
                }
            } else {
                company.percentage = 0;
            }
            if (company.price && company.startPrice) {
                company.increase = ((company.price - company.startPrice) / company.startPrice) * 100;
            }
        });
        state.companies.sort((c1, c2) => {
            if (!c1.percentage && !c2.percentage) {
                return 1;
            }
            if (!c1.percentage) {
                return 1;
            }
            if (!c2.percentage) {
                return -1;
            }
            return c2.percentage - c1.percentage;
        });
    }

    const dragCompany = (oldIndex: number, newIndex: number) => {
        const current = state.companies.splice(oldIndex, 1)[0];
        if (current) {
            state.companies.splice(newIndex, 0, current);
        }
    };
    const updateCompany = async (company: Company) => {
        const index = state.companies.findIndex((c) => c.code === company.code);
        if (index >= 0) {
            state.companies.splice(index, 1, company);
        } else {
            state.companies.push(company);
        }
    };

    const removeCompany = async (company: Company) => {
        const index = state.companies.findIndex((c) => c.code === company.code);
        if (index >= 0) {
            state.companies.splice(index, 1);
        }
    };

    const exportTracker = (type: ExportType) => {
        if (type === ExportType.JSON) {
            return JSON.stringify(state);
        }
        return state.companies.filter((c) => c.shares && c.percentage)
            .reduce((value, current) => `${value + current.exportMarkdownRow()}\n`, exportMarkdownHeader);
    };

    const importTracker = (json: string) => {
        let imported: Tracker = {} as Tracker;
        try {
            imported = JSON.parse(json) as Tracker;
        } catch (e) {
            ElMessage.error({
                message: '格式错误，导入失败!',
            });
            return;
        }
        localStorage.setItem(KEY, json);
        state.cash = imported.cash;
        state.exchangeRate = imported.exchangeRate;
        const companyList: Company[] = [];
        imported.companies.forEach((company) => companyList.push(new Company(company)));
        state.companies = companyList;
    };
    return {
        ...toRefs(state),
        updateCompanyValuePercentage,
        exportTracker,
        importTracker,
        handlers: {
            updateCompany,
            removeCompany,
            dragCompany,
        },
    };
}
